from math import sqrt
from datetime import datetime
import abc


class MyMath:
    def add(self, x, y):
        return x + y

    def minus(self, x, y):
        return x - y


    def mul(self, x, y):
        return x * y


    def div(self, x, y):
        try:
            x / y
        except ZeroDivisionError:
            return '除数不能为0'
        else:
            return x / y


    def sqrt(self, x):
        return sqrt(x)


    @staticmethod
    def classadd(x, y):
        return x + y


# 实例方法
counter = MyMath()
print('-'*20, '实例方法', '-'*20)
print(f"x + y = {counter.add(5, 7)}")
print(f"x - y = {counter.add(5, 7)}")
print(f"x / y = {counter.div(5, 0)}")
print(f"x * y = {counter.mul(5, 8.2)}")

# 类方法
print('-'*20, '类方法', '-'*20)
print(f"x + y = {MyMath.classadd(5, 7)}")
print('实例方法：1.在定义类时需要self形参；2.需要一个实例并将实例进行__init__初始化')
print('类方法：1.在定义类时不需要self形参；2.不需要一个实例')
"""
用类实现计算器的打印结果
-------------------- 实例方法 --------------------
x + y = 12
x - y = 12
x / y = 除数不能为0
x * y = 41.0
-------------------- 类方法 --------------------
x + y = 12
实例方法：1.在定义类时需要self形参；2.需要一个实例并将实例进行__init__初始化
类方法：1.在定义类时不需要self形参；2.不需要一个实例
"""


print('-'*20, '定义类：基金', '-'*20)
# 抽象一个基金类（抽象基类）
"""
属性：申购费、赎回费、当日净值、规模、十大重仓品种（私有）、基金公司、基金经理
方法：申购、赎回、分红、转换、计算某笔申购的当前持有天数、计算盈亏，获取历史某日的净值
"""


# 子类继承抽象基类并细分
"""
根据投资标的不同分为：股票型基金、指数型基金、债券型基金，与抽象基类属性和方法一致
"""


# 实例：具体的基金
"""
实例属性：申购日期，申购金额，持有份额（私有），赎回日期，赎回份额，赎回金额（私有）
实例方法：无
"""


class Funds:
    purchase_cost = 0.012       # 申购费
    __redemptive_cost = 0.005     # 赎回费，私有属性
    net_value = {'2020/11/10': 0.90, datetime.today().strftime("%Y/%m/%d"): 1}               # 以字典形式保存的净值
    pass


    # 静态方法获取类的私有属性
    @classmethod
    def get_redemptive_cost(cls):
        print(f'当前赎回费是{cls.__redemptive_cost}')
        return cls.__redemptive_cost


    # 方法：申购，返回确认份额
    def buying(self, money, date):
        global buyed_money
        buyed_money = money
        def got_value(date):
            value = Funds.net_value.get(date)  # 获取日期对应的净值
            return value

        value = got_value(date)
        fund_shares = buyed_money * (1 - self.purchase_cost) / value      # 计算应得的基金份额
        return fund_shares


    # 方法：赎回，返回赎回金额
    def selling(self, fund_shares, date):
        def got_value(date):
            value = Funds.net_value.get(date)  # 获取日期对应的净值
            return value
        value = got_value(date)
        global sold_money
        sold_money = fund_shares * value * (1 - self._Funds__redemptive_cost)       # 访问了类的私有属性
        return sold_money


    # 方法：计算盈亏
    def profits(self):
        profits = sold_money - buyed_money
        return profits




class StockFunds(Funds):
    fundstype = 'bondfund'     # 这是股票型基金


print(f'当前赎回费是{StockFunds.get_redemptive_cost()}')


# 实例化一支基金
xqhyA = StockFunds()
print('实例化一支基金:兴合全宜A')
shares = xqhyA.buying(10000, '2020/11/10')        # 得到持有份额
print(f'买入获得基金份额：{shares}')
money = xqhyA.selling(shares, '2020/11/14')       # 得到最终资金
print(f'卖出获得现金：{money}')
profits = xqhyA.profits()
print(f'操作盈亏：{profits}')

# 运行结果
"""
-------------------- 定义类：基金 --------------------
买入获得基金份额：10977.777777777777
卖出获得现金：10922.888888888889
操作盈亏：922.8888888888887
"""


# 定义债券型基金，继承基金(抽象基类)
print('-'*20, '__init__中初始化', '-'*20)
class BondFunds(Funds):
    fundstype = 'bondfund'     # 这是债券型基金
    def __init__(self):
        self.buy_stock = False       # 假设债券型基金不能买股票
        self.__new_stock = True      # 但是可以进行股票打新，实例的私有属性

    def __str__(self):          # 定义__str__
        return '债券基金，稳健理财'


bondfund1 = BondFunds()
"""
以下关于债券基金的概念并不完全准确
"""
print("有一只债券型基金持有股票")
print(f"债券型基金能买股票，{bondfund1.buy_stock}")
print(f"原来债券型基金可以打新，{bondfund1._BondFunds__new_stock}")
print(bondfund1)